home *** CD-ROM | disk | FTP | other *** search
/ Gekkan Dennou Club 140 / Gekkan Dennou Club - 2000.1 Vol. 140 (Japan).7z / Gekkan Dennou Club - 2000.1 Vol. 140 (Japan) (Track 1).bin / tools / dshell / dsh333bs.lzh / dshell.c < prev    next >
C/C++ Source or Header  |  1999-12-05  |  8KB  |  370 lines

  1. /*
  2.     dshell    v3
  3.  
  4.     ファイル読込・展開用バッファ管理等
  5. */
  6.  
  7. #include    "dsh.h"
  8.  
  9. #define    STACK_MARGIN    (4*1024)    // ネスト限界を決めるスタック残り容量
  10.  
  11. /*
  12.     テキストの“要nM”チェック
  13. */
  14. static void
  15. checkMemory(void *head)
  16. {
  17.     void *p;
  18.     int n;
  19.     char temp[64];
  20.     
  21.     n = MALLOC(MALLOC(-1) & 0x00ffffff);
  22.     if (n < 0)
  23.         return;
  24.     MFREE(n);
  25.     p = (void *)n - 0x10;
  26.     if (p <= (void *)0x100000)
  27.         return;
  28.     for (n = 0x200000; p > (void *)n; n += n)
  29.         ;
  30.     n >>= 1;
  31.     p = head - 0x10;
  32.     if (p <= (void *)n) {
  33.         ushort shiftKeys;
  34.  
  35.         w_open();
  36.         sprintf(temp, "%dMB 境界を越えました", n >> 20);
  37.         w_mes(0, temp);
  38.         shiftKeys = B_SFTSNS();
  39.         if (!(shiftKeys & LED_CODEIN) || !(shiftKeys & (LED_ROMA | LED_KANA)))
  40.             w_wait(99);
  41.     }
  42. }
  43.  
  44. static void
  45. fileNotFound(const uchar *fname)
  46. {
  47.     char temp[96];
  48.     const uchar *p = fname;
  49.     uchar c;
  50.  
  51.     while ((c = *p++) >= '\x20')
  52.         ;
  53.     if (*--p == '\0')
  54.         sprintf(temp, "ファイル(%.32s)が見つかりません", fname);
  55.     else
  56.         sprintf(temp, "ファイル名に誤りがあります", fname);
  57.     dabort(temp);
  58. }
  59.  
  60. static void
  61. cut_free(int cut_no)
  62. {
  63.     for (; cut_no < CUT_MAX && cut[cut_no].fname != NULL; cut_no++) {
  64.         cut[cut_no].fname = NULL;
  65.         if (cut[cut_no].ptr != NULL) {
  66.             if (MFREE(cut[cut_no].ptr))
  67.                 d_mfree();
  68.         }
  69.     }
  70. }
  71.  
  72. static void
  73. freeFont(int fontNo)
  74. {
  75.     for (; fontNo < FONTMAX && font16[fontNo].fname != NULL; fontNo++) {
  76.         font16[fontNo].fname = NULL;
  77.         if (font16[fontNo].pat != NULL) {
  78.             if (MFREE(font16[fontNo].pat))
  79.                 d_mfree();
  80.         }
  81.     }
  82. }
  83.  
  84.  
  85. /*
  86.     ファイル読込・展開・ポインタテーブル用意
  87.  
  88.     テキストデータ展開用+行ポインタテーブル用領域確保
  89.  
  90.     テキストデータ展開と行ポインタ展開とで双方から食っていき
  91.     行ポインタテーブルは逆順から正順に戻しつつ展開後のテキストの
  92.     後ろに移動。余った部分はsetblockで解放。
  93.  
  94.      -------    ==================    ==================    ==================
  95.     ↑    大域変数待避領域    大域変数待避領域    大域変数待避領域
  96.         ------------------    ------------------    ------------------
  97.          テキスト展開領域     展開後のテキスト     展開後のテキスト
  98.      MALLOCで          +-------        :            :
  99.         ----------+        ------------------    ------------------
  100.      確保した        ↓                    行ポインタ(正順)
  101.                    ->      (余った領域)   ->        :
  102.      ブロック        ↑ +-----    ------------------    ------------------
  103.         -----------+            :        (SETBLOCKで解放)
  104.              行ポインタ(逆順)    行ポインタ(逆順)        :
  105.         ------------------    ------------------        :
  106.     ↓    ファイル読込領域    ファイル読込領域        :
  107.      -------    ==================    ==================    ==================
  108. */
  109. static inline int 
  110. dshell_sub(char *fname)
  111. {
  112.     typedef struct {
  113.         // 親テキストについての情報待避用
  114.         char *filename;
  115.         int lp;
  116.         int lpmx;
  117.         uchar **lhp;
  118.         int curLine;
  119.         int exeLine;
  120.         ushort textColor;
  121.         ushort bgColor;
  122.         CUT *bgCut;
  123.         int Cut_Begin;
  124.         int curFontNo;
  125.         SHELLVAR *sysVar;
  126.         short defGMODE;
  127.  
  128.         // テキスト本体
  129.         uchar contents[0];
  130.     } TEXTHEAD;
  131. #define    hp    ((TEXTHEAD *)ptr)
  132.     void *ptr, *ptr2;
  133.     int n;
  134.     static uchar noCtrlCharFlag;
  135.  
  136.     w_open();
  137.     w_load();
  138.  
  139.     noCtrlCharFlag = FALSE;
  140.     if (*fname == '!') {
  141.         fname++;
  142.         noCtrlCharFlag = TRUE;
  143.     }
  144.  
  145.     {
  146.         FILE *fp;
  147.         int size;
  148.  
  149.         fp = fopen(fname, "rb");
  150.         if (fp == NULL || (n = dfilelength(fileno(fp))) < 0) {
  151.             fileNotFound(fname);
  152.             return -1;
  153.         }
  154.         do {
  155.             /*
  156.                 テキストデータ展開用+行ポインタテーブル用領域確保
  157.             */
  158.             size = MALLOC(-1) & 0x00ffffff;    /* まず空きサイズを知る */
  159.  
  160.             /* ファイル読み込み分なかったら帰る(仕様変更予定あり) */
  161. #define    MINSIZ    512        // 若干のゆとり
  162.             if (size <= n + MINSIZ) {
  163.                 d_mem();
  164.                 fclose(fp);
  165.                 return -1;
  166.             }
  167.  
  168.             /*
  169.                 で、とりあえずめいっぱい確保する
  170.             */
  171.             ptr = (void *)MALLOC(size);
  172.         } while ((int)ptr < 0);
  173.  
  174.         /*
  175.             テキストデータ読み込み用バッファ先頭
  176.             =仮の行ポインタテーブル末尾を決める
  177.         */
  178.         ptr2 = (void *)(((int)ptr + size - (n + 2)) & -4);    // +2 は終端コードの分
  179.  
  180.         if (n > 0) {
  181.             if (fread(ptr2, sizeof(char), n, fp) != n) {
  182.                 d_read();    /* 'ファイル読み込みエラー' */
  183.                 if (MFREE(ptr)) {
  184.                     d_mfree();
  185.                 }
  186.                 fclose(fp);
  187.                 return -1;
  188.             }
  189.         }
  190.         fclose(fp);
  191.         *(uchar *)(ptr2 + n) = 0x1a;    /* 終端コード */
  192.         *(uchar *)(ptr2 + n + 1) = 0x1a;    // 末尾に2バイト文字の第1バイトがあった場合の予備
  193.     }
  194.  
  195.     hp->filename = filename;
  196.     hp->lp = lp;
  197.     hp->lpmx = lpmx;
  198.     hp->lhp = lhp;
  199.     hp->curLine = curLine;
  200.     hp->exeLine = exeLine;
  201.     hp->textColor = tx_col[3];
  202.     hp->bgColor = gr_col[0];
  203.     hp->bgCut = bgCut;
  204.     hp->Cut_Begin = Cut_Begin;
  205.     hp->curFontNo = curFontNo;
  206.     hp->sysVar = sysVarListHead;
  207.     hp->defGMODE = defGMODE;
  208.  
  209.     {
  210.         short bmid;        /* bookmark id 保存(メモ)用 */
  211.         unsigned short tcrc;    /* 保持用 */
  212.  
  213.         /*
  214.             表示用にテキストを整理
  215.         */
  216.         if (n > 4*1024) {
  217.             w_mes(0, "ファイルの整理中です");
  218.             w_mes(1, "しばらくお待ち下さい");
  219.         }
  220.  
  221.         tcrc = calc_crc(0, ptr2, n);
  222.  
  223.         ptr2 = sort(ptr + offsetof(TEXTHEAD, contents), ptr2, fname, n, noCtrlCharFlag, ptr);
  224.         if (ptr2 == NULL) {
  225.             d_mem();
  226.             if (MFREE(ptr)) {
  227.                 d_mfree();
  228.             }
  229.             return -1;
  230.         }
  231.  
  232.         if (SETBLOCK(ptr, ptr2 - ptr)) {
  233.             w_open();
  234.             w_mes(0, "メモリブロックのサイズ変更ができません");
  235.             w_mes(2, "全ての処理を中断します");    /* 処理を続行するとアブナイようなので… */
  236.             w_wait(0);
  237.             dsh_abort(1);
  238.         }
  239.  
  240.         Cut_Begin = cut_job_read(Cut_Begin);
  241.         curFontNo = readFontFile(curFontNo);
  242.  
  243.         /*
  244.             現読込中ファイルだったら登録関係は一切せず、
  245.             新規表示開始位置は0
  246.         */
  247.         bmid = crc_to_IMAno(tcrc);
  248.         if (bmid >= 0) {
  249.             lp = 0;
  250.             bmid = -1;        /* bmid は兼フラグ */
  251.         } else {
  252.             bmid = crc_to_KAKOno(tcrc);
  253.             if (bmid != -1) {
  254.                 lp = get_ln(bmid);
  255.                 if (lp < 0) {
  256.                     lp = 0;        /* errorなんで */
  257.                     bmid = -1;
  258.                 }
  259.             } else {
  260.                 bmid = regist_IMAmark(tcrc);    /* errorだった場合登録せず(-1が返るので登録関係はいじらない結果になる。でもまず起きないエラー) */
  261.                 set_fnm_to_mark(bmid, fname);
  262.                 lp = 0;
  263.             }
  264.         }
  265.  
  266.         /*
  267.             閲覧
  268.         */
  269.         filename = fname;
  270.         defGMODE = GMODE;
  271.         if (debugMode)
  272.             checkMemory(ptr);
  273.  
  274.         if (GMODE == 0 && hp->bgCut != bgCut)
  275.             resetBG();
  276.         n = get_event();
  277.  
  278.         if (bmid >= 0) {
  279.             put_ln(bmid, lp);
  280.             IMAtoKAKO(bmid);
  281.             set_fnm_to_mark(bmid, NULL);
  282.         }
  283.  
  284.         resetBgFlag = (GMODE > 0 || hp->bgCut != bgCut);
  285.     }
  286.  
  287.     filename = hp->filename;
  288.     lp = hp->lp;
  289.     lpmx = hp->lpmx;
  290.     lhp = hp->lhp;
  291.     curLine = hp->curLine;
  292.     exeLine = hp->exeLine;
  293.     tx_col[3] = hp->textColor;
  294.     gr_col[0] = hp->bgColor;
  295.     bgCut = hp->bgCut;
  296.     Cut_Begin = hp->Cut_Begin;
  297.     curFontNo = hp->curFontNo;
  298.     defGMODE = hp->defGMODE;
  299.  
  300.     /*
  301.         オシマイの処理
  302.     */
  303.     /* cut ↓:領域開放 */
  304.     cut_free(Cut_Begin);
  305.     /* cut ↑ */
  306.  
  307.     freeFont(curFontNo);
  308.     freeMenu(ptr);
  309.     while (hp->sysVar != sysVarListHead) {
  310.         SHELLVAR *vp = sysVarListHead;
  311.         sysVarListHead = vp->next;
  312.         free(vp);
  313.     }
  314.  
  315.     if (MFREE(ptr)) {
  316.         d_mfree();
  317.     }
  318.     return n;
  319. }
  320.  
  321.  
  322. /*
  323.     ファイル読込ネスト管理
  324.  
  325.     (global) nest:呼び出されレベル(0なら一番初めの呼び出し:復帰不可)
  326. */
  327. void 
  328. dshell(char *fname)
  329. {
  330.     static int n;
  331.  
  332.     if (getSp() - _SSTA < STACK_MARGIN) {
  333.         w_open();
  334.         w_mes(0, "作業領域がいっぱいです");
  335.         w_mes(2, "これ以上読み込めません");
  336.         w_mes(3, "(STACK OVERFLOW 回避措置)");    /* そのうちスタック使わんように改造するか…? */
  337.         w_wait(0);
  338.         w_close();
  339.         return;
  340.     }
  341.  
  342.     nest++;
  343.     while ((n = dshell_sub(fname)) > 0) {
  344.         /*
  345.             登録キーによるエディタの起動
  346.         */
  347.         char *p;
  348.         char *temp = malloc(256);
  349.         if (temp == NULL)
  350.             break;
  351.         if ((p = getenv("DSHELL_EDITOR")) != NULL || (p = getenv("EDITOR")) != NULL) {
  352.             char *q = strchr(p, '#');
  353.             if (q == NULL) {
  354.                 strcpy(temp, p);
  355.             } else {
  356.                 strncpy(temp, p, q - p);
  357.                 itoa(n, temp + (q - p), 10);
  358.                 strcat(temp, ++q);
  359.             }
  360.             strcat(temp, " ");
  361.             strcat(temp, fname + (*fname == '!'));
  362.             nouse_fnk();
  363.             C_WIDTH(0);
  364.             dexec(temp, DEX_FKON);
  365.         }
  366.         free(temp);
  367.     }
  368.     nest--;
  369. }
  370.